using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IBS.ServiceContracts;
using NUnit.Framework;
using IBS.Model;
using IBS.Dal;
using IBS.Model.Base;
using log4net;

namespace IBS.Bll.Accounts
{

    public class CurrencyService : ServiceBase, ICurrencyService
    {
        #region Fields

        private static readonly ILog log = LogManager.GetLogger(typeof(CurrencyService));
        private CurrencyValidator currencyValidator;

        #endregion
        #region Constructors

        public CurrencyService(IIbsContext context)
            : base(context)
        {
            currencyValidator = new CurrencyValidator(context);
        }

        #endregion
        #region Members

        public Currency GetCurrency(string ISO)
        {
            Currency result;
            try
            {
                result = _context.Currencies.Single(c => c.ISO == ISO);
            }
            catch (InvalidOperationException)
            {
                throw new BusinessException(String.Format("{0} is not correct currency", ISO));
            }
            return result;
        }

        public decimal GetAskRate(string ISO)
        {
            return  GetCurrentRates(ISO).AskRate;
        }

        public decimal GetBidRate(string ISO)
        {
            return GetCurrentRates(ISO).BidRate;
        }

        public Currency GetBaseCurrency()
        {
            return GetCurrency(GetBaseCurrencyISO());
        }

        public string GetBaseCurrencyISO()
        {
            return "BYR";
        }

        public IList<Currency> GetAllCurrencies()
        {
            var currencies = _context.Currencies.ToList();
            return currencies;
        }

        public CurrencyExchangeRate GetCurrentRates(string ISO)
        {

            var currentCurrencyRate = (from rate in _context.CurrencyExchangeRates
                                       where rate.Currency.ISO == ISO
                                       orderby rate.Date descending
                                       select rate).FirstOrDefault();
             if (currentCurrencyRate == null)
                throw new BusinessException(String.Format("{0} currency doesn't have any rate", ISO));
            return currentCurrencyRate;
        }

        public void SetCurrencyExchangeRate(string ISO, CurrencyExchangeRate rate)
        {
            var currentCurrency = _context.Currencies.Single(c => c.ISO == ISO);

            rate.Date = DateTime.Now;
            if (!currencyValidator.IsValidAskRate(rate))
                throw new BusinessException("Rate is not valid");
            currentCurrency.CurrencyExchangeRate.Add(rate);
            _context.SaveChanges();

        }
        #endregion


        public decimal GetExpectedAmount(string fromISO, string toISO, decimal amount)
        {
            if (fromISO == toISO)
                return amount;

            if (fromISO == GetBaseCurrencyISO())
                return amount * GetAskRate(toISO);

            if (toISO == GetBaseCurrencyISO())
                return amount;

            throw new BusinessException(String.Format("One of accounts must have {0} currency", GetBaseCurrencyISO()));
        }
    }
}
